package hotboxr::Model::Mongo;

use Moose;
BEGIN { extends 'Catalyst::Model::MongoDB' };
use MongoDB::GridFS;
use MongoDB::OID;
use Math::Round;
use Data::Dumper;

sub insert_wrap {
    my ($self,$cname,$params) = @_;
    my $collection = $self->c($cname);
    eval {$collection->insert($params)};
    if ($@) { warn $@; return 0;}
    return 1;
}
sub get_contributor {
    my ($self,$ip) = @_;
    my $contributor = $self->find_contributor_by_ip($ip) || undef;
    return $contributor if defined $contributor;
    my $contributor_oid = $self->insert_wrap('contributors',{
            ip_address => $ip,
            num_uploads => 0,
            num_reported => 0,
            num_verified => 0,
            banned => 0
    });
    $contributor = $self->find_contributor_by_oid($contributor_oid);
    return $contributor || undef;
}
sub find_contributor_by_oid {
    my ($self,$oid) = @_;
    if (!ref($oid)) { $oid = $self->id_to_oid($oid); }#scalars
    elsif (ref($oid) ne "MongoDB::OID") { return 0; }
    my $col = $self->c('contributors');
    return $col->find_one({_id => $oid});
}
sub find_contributor_by_ip {
    my ($self,$ip) = @_;
    my $col = $self->c('contributors');
    return $col->find_one({ip_address => $ip});
}

sub increment {
    my($self,$cname,$field,$id) = @_;
    my $col = $self->c($cname);
    return $col->update({'_id'=>$id},{'$inc'=>{$field => 1}}); 
}   

sub store_image {
    my ($self,$path,$filetype,$contributor_id,$category) = @_;
    my $grid = $self->db->get_gridfs;
    my $img = IO::File->new($path, "r");
    #my $oid = 
    return $grid->put($img,{ 
        file_type => $filetype, 
        contributor_id => $contributor_id, 
        revoked => 0, 
        verification_score => 0, 
        verified => 0,
        category => $category, 
    });
}

sub get_random_image {
    my ($self,$category,$allow_unverified) = @_;
    my $params = {revoked => 0};
    if ($category ne 'all') { $params->{category} = $category; }
    if (!$allow_unverified) { $params->{verified} = 1; }

    my $grid = $self->db->get_gridfs;
    #method 2 db.fs.files.find().limit(-1).skip( _rand() * c.count() );
    my $count = $grid->files->count($params);
    my $random_file = $grid->files->query($params)->limit(-1)->skip(round($count * rand))->next;
    return undef unless defined $random_file;
    my $image = $grid->find_one({_id => $random_file->{_id}}); 
    return $image || undef;
}

sub adjust_image_score {
    my ($self,$image_id,$rate) = @_;
    my $grid = $self->db->get_gridfs;
    #TODO real scoring algorithm
    $grid->files->update({_id => $image_id}, {'$inc' =>  { verification_score => $rate*1}});
    my $image = $grid->files->find_one({_id => $image_id});
    warn "score: $image->{verification_score} | threshold: " . $self->config->{verification_threshold};
    if ($image->{verification_score} >= $self->config->{verification_threshold}) {
        warn "verification score is above threshold";
        $grid->files->update({_id => $image_id}, {'$set' => {verified => 1}});
    } 
}

sub add_report {
    my ($self,$contributor,$image_id,$type,$details) = @_;
    $image_id = $self->id_to_oid($image_id) if ref($image_id) ne 'MongoDB::OID';
    return 0 if $self->check_if_already_reported($contributor,$image_id);
    $self->insert_wrap('reports',{
        contributor_id => $contributor->{_id},
        image_id => $image_id,
        type => $type,
        details => $details 
    });
    $self->adjust_image_score($image_id,($type eq 'verify' ? 1 : -1));
    $self->increment('contributors','num_' . ($type eq 'verify' ? 'verified' : 'reported'), $contributor->{_id});
}

sub check_if_already_reported {
    my ($self,$contributor,$image_id) = @_;
    my $col = $self->c('reports');
    return $col->find_one({contributor_id => $contributor->{_id}, image_id => $image_id});
}

sub is_name_available {
    my ($self,$name) = @_;
    my $col = $self->c('users');
    return $col->find_one({name => $name});
}

sub id_to_oid { 
    my ($self,$id) = @_;
    return MongoDB::OID->new(value => $id);
}

=head1 NAME

hotboxr::Model::Mongo - MongoDB Catalyst model component

=head1 SYNOPSIS

See L<hotboxr>.

=head1 DESCRIPTION

MongoDB Catalyst model component.

=head1 AUTHOR

A clever guy

=head1 LICENSE

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut

no Moose;
__PACKAGE__->meta->make_immutable;

1;
